﻿// <copyright>
// Project: sofort.NET
// Date:  2014 - 02 - 04
// Copyright: Karl Haak 2014
// </copyright>
// <author>Karl Haak (www.karlhaak.de)</author>
using System;
using System.Globalization;
using System.Linq;
using System.Xml.Linq;
using pay.sofort.Models;

namespace pay.sofort
{
    public static class TPaySofortXml
    {
        #region ### object to xml ###

        public static XDocument CreateXDocumentMultipay(PaySofortMultipay paySofortMultipay)
        {
            var xDocument = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
            var multipay = new XElement("multipay");
            multipay.Add(new XElement("project_id", paySofortMultipay.project_id));
            multipay.Add(new XElement("language_code", paySofortMultipay.language_code));
            if (paySofortMultipay.timeout.HasValue) multipay.Add(new XElement("timeout", paySofortMultipay.timeout));
            multipay.Add(new XElement("interface_version", paySofortMultipay.interface_version));
            multipay.Add(new XElement("amount",
                paySofortMultipay.amount.ToString(CultureInfo.GetCultureInfo("EN"))));
            multipay.Add(new XElement("currency_code", paySofortMultipay.currency_code));

            var xReasons = new XElement("reasons");
            xReasons.Add(new XElement("reason", paySofortMultipay.reason_1));
            xReasons.Add(new XElement("reason", paySofortMultipay.reason_2));
            multipay.Add(xReasons);

            var xUserVariables = new XElement("user_variables");
            xUserVariables.Add(new XElement("user_variable", paySofortMultipay.user_variable_1));
            multipay.Add(xUserVariables);

            if (!String.IsNullOrWhiteSpace(paySofortMultipay.success_url))
            {
                multipay.Add(new XElement("success_url", paySofortMultipay.success_url));
                multipay.Add(new XElement("success_link_redirect", "1"));
            }
            if (!String.IsNullOrWhiteSpace(paySofortMultipay.success_url))
                multipay.Add(new XElement("abort_url", paySofortMultipay.abort_url));
            if (!String.IsNullOrWhiteSpace(paySofortMultipay.success_url))
                multipay.Add(new XElement("timeout_url", paySofortMultipay.timeout_url));


            var xNotificationUrls = new XElement("notification_urls");
            xNotificationUrls.Add(new XElement("notification_url", paySofortMultipay.notification_url_1,
                new XAttribute("notify_on", paySofortMultipay.notification_url_1_notify_on)));
            xNotificationUrls.Add(new XElement("notification_url", paySofortMultipay.notification_url_2,
                new XAttribute("notify_on", paySofortMultipay.notification_url_2_notify_on)));
            multipay.Add(xNotificationUrls);

            var xSu = new XElement("su");
            xSu.Add(new XElement("customer_protection", 0));
            multipay.Add(xSu);

            xDocument.Add(multipay);

            return xDocument;
        }

        public static XDocument CreateXDocumentTransactionRequest(
            PaySofortTransactionRequest paySofortTransactionRequest)
        {
            var xDocument = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
            var transaction_request = new XElement("transaction_request", new XAttribute("version", 2));
            transaction_request.Add(new XElement("transaction", paySofortTransactionRequest.transaction_key));
            xDocument.Add(transaction_request);
            return xDocument;
        }

        #endregion

        #region ### xml to object ###

        public static PaySofortNewTransaction CreatePaySofortNewTransaction(string xmlIn, string username)
        {
            XDocument xDocument = XDocument.Parse(xmlIn);
            if (xDocument.Root == null || xDocument.Root.Name != "new_transaction")
            {
                throw new ApplicationException("Not a new_transation document");
            }
            string transaction = xDocument.Descendants("transaction").First().Value.Trim();
            string payment_url = xDocument.Descendants("payment_url").First().Value.Trim();

            PaySofortNewTransaction paySofortNewTransaction =
                new PaySofortNewTransaction {transaction_key = transaction, payment_url = payment_url}.SetNew(username);

            return paySofortNewTransaction;
        }

        public static PaySofortTransaction CreateTransaction(string xmlIn, TPaySofortConfig config)
        {
            XDocument xDocument = XDocument.Parse(xmlIn);
            if (xDocument.Root == null || xDocument.Root.Name != "transactions")
            {
                throw new ApplicationException("Not a transactions document");
            }

            XElement td = xDocument.Descendants("transaction_details").First();


            PaySofortTransaction paySofortTransaction =
                new PaySofortTransaction
                {
                    project_id = (int?) td.Element("project_id") ?? config.ProjectId,
                    transaction_key = (string) td.Element("transaction"),
                    test = (bool?) td.Element("test") ?? false,
                    transaction_created = (DateTime) td.Element("time"),
                    status = (string) td.Element("status"),
                    status_reason = (string) td.Element("status_reason"),
                    status_modified = (DateTime?) td.Element("status_modified"),
                    payment_method = (string) td.Element("payment_method"),
                    language_code = (string) td.Element("language_code"),
                    amount = (decimal) td.Element("amount"),
                    currency_code = (string) td.Element("currency_code"),
                    email_customer = (string) td.Element("email_customer"),
                    phone_customer = (string) td.Element("phone_customer"),
                    exchange_rate = ((decimal?) td.Element("exchange_rate") ?? 1m),
                }.SetNew(config.Username);


            XElement sender = td.Element("sender");
            if (sender != null)
            {
                paySofortTransaction.sender_holder = (string) sender.Element("holder");
                paySofortTransaction.sender_account_number = (string) sender.Element("account_number");

                paySofortTransaction.sender_bank_code = (string) sender.Element("bank_code");
                paySofortTransaction.sender_bank_name = (string) sender.Element("bank_name");
                paySofortTransaction.sender_country_code = (string) sender.Element("country_code");
                paySofortTransaction.sender_iban = (string) sender.Element("iban");
                paySofortTransaction.sender_bic = (string) sender.Element("bic");
            }

            XElement recipient = td.Element("recipient");
            if (recipient != null)
            {
                paySofortTransaction.recipient_holder = (string) recipient.Element("holder");
                paySofortTransaction.recipient_account_number = (string) recipient.Element("account_number");
                paySofortTransaction.recipient_bank_code = (string) recipient.Element("bank_code");
                paySofortTransaction.recipient_bank_name = (string) recipient.Element("bank_name");
                paySofortTransaction.recipient_country_code = (string) recipient.Element("country_code");
                paySofortTransaction.recipient_iban = (string) recipient.Element("iban");
                paySofortTransaction.recipient_bic = (string) recipient.Element("bic");
            }

            XElement costs = td.Element("costs");
            if (costs != null)
            {
                paySofortTransaction.costs_fee = (decimal) td.Element("costs").Element("fees");
                paySofortTransaction.costs_currency_code = (string) td.Element("costs").Element("currency_code");
                paySofortTransaction.costs_exchange_rate = (decimal) td.Element("costs").Element("exchange_rate");
            }


            paySofortTransaction.status_history = (string) td.Element("status_history_items");
            paySofortTransaction.amount_refunded = (decimal?) td.Element("amount_refunded") ?? 0.00m;
            paySofortTransaction.su_consumer_protection = td.Element("su") != null
                ? (bool?) td.Element("su").Element("consumer_protection")
                : null;

            return paySofortTransaction;
        }

        public static PaySofortStatusNotfication CreatePaySofortStatusNotfication(string xmlIn, string username,
            string responseUrl, string statusService)
        {
            XDocument xDocument = XDocument.Parse(xmlIn);
            if (xDocument.Root == null || xDocument.Root.Name != "status_notification")
            {
                throw new ApplicationException("Not a status_notification document");
            }
            var transaction_key = (string) xDocument.Descendants("transaction").First();
            var time = (DateTime) xDocument.Descendants("time").First();

            PaySofortStatusNotfication paySofortNewTransaction =
                new PaySofortStatusNotfication
                {
                    transaction_key = transaction_key,
                    time = time,
                    ResponseUrl = responseUrl,
                    status = statusService
                }.SetNew(username);

            return paySofortNewTransaction;
        }

        #endregion
    }
}